home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-10-30 | 37.3 KB | 1,057 lines |
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- NNNNAAAAMMMMEEEE
- perlXStut - Tutorial for XSUBs
-
- DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
- This tutorial will educate the reader on the steps involved in creating a
- Perl extension. The reader is assumed to have access to the _p_e_r_l_g_u_t_s
- manpage and the _p_e_r_l_x_s manpage.
-
- This tutorial starts with very simple examples and becomes more complex,
- with each new example adding new features. Certain concepts may not be
- completely explained until later in the tutorial to ease the reader
- slowly into building extensions.
-
- VVVVEEEERRRRSSSSIIIIOOOONNNN CCCCAAAAVVVVEEEEAAAATTTT
-
- This tutorial tries hard to keep up with the latest development versions
- of Perl. This often means that it is sometimes in advance of the latest
- released version of Perl, and that certain features described here might
- not work on earlier versions. This section will keep track of when
- various features were added to Perl 5.
-
- +o In versions of Perl 5.002 prior to the gamma version, the test script
- in Example 1 will not function properly. You need to change the "use
- lib" line to read:
-
- use lib './blib';
-
-
- +o In versions of Perl 5.002 prior to version beta 3, the line in the
- .xs file about "PROTOTYPES: DISABLE" will cause a compiler error.
- Simply remove that line from the file.
-
- +o In versions of Perl 5.002 prior to version 5.002b1h, the test.pl file
- was not automatically created by h2xs. This means that you cannot
- say "make test" to run the test script. You will need to add the
- following line before the "use extension" statement:
-
- use lib './blib';
-
-
- +o In versions 5.000 and 5.001, instead of using the above line, you
- will need to use the following line:
-
- BEGIN { unshift(@INC, "./blib") }
-
-
- +o This document assumes that the executable named "perl" is Perl
- version 5. Some systems may have installed Perl version 5 as
- "perl5".
-
-
-
-
-
-
- PPPPaaaaggggeeee 1111
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- DDDDYYYYNNNNAAAAMMMMIIIICCCC VVVVEEEERRRRSSSSUUUUSSSS SSSSTTTTAAAATTTTIIIICCCC
-
- It is commonly thought that if a system does not have the capability to
- load a library dynamically, you cannot build XSUBs. This is incorrect.
- You _c_a_n build them, but you must link the XSUB's subroutines with the
- rest of Perl, creating a new executable. This situation is similar to
- Perl 4.
-
- This tutorial can still be used on such a system. The XSUB build
- mechanism will check the system and build a dynamically-loadable library
- if possible, or else a static library and then, optionally, a new
- statically-linked executable with that static library linked in.
-
- Should you wish to build a statically-linked executable on a system which
- can dynamically load libraries, you may, in all the following examples,
- where the command "make" with no arguments is executed, run the command
- "make perl" instead.
-
- If you have generated such a statically-linked executable by choice, then
- instead of saying "make test", you should say "make test_static". On
- systems that cannot build dynamically-loadable libraries at all, simply
- saying "make test" is sufficient.
-
- EEEEXXXXAAAAMMMMPPPPLLLLEEEE 1111
-
- Our first extension will be very simple. When we call the routine in the
- extension, it will print out a well-known message and return.
-
- Run h2xs -A -n Mytest. This creates a directory named Mytest, possibly
- under ext/ if that directory exists in the current working directory.
- Several files will be created in the Mytest dir, including MANIFEST,
- Makefile.PL, Mytest.pm, Mytest.xs, test.pl, and Changes.
-
- The MANIFEST file contains the names of all the files created.
-
- The file Makefile.PL should look something like this:
-
- use ExtUtils::MakeMaker;
- # See lib/ExtUtils/MakeMaker.pm for details of how to influence
- # the contents of the Makefile that is written.
- WriteMakefile(
- 'NAME' => 'Mytest',
- 'VERSION_FROM' => 'Mytest.pm', # finds $VERSION
- 'LIBS' => [''], # e.g., '-lm'
- 'DEFINE' => '', # e.g., '-DHAVE_SOMETHING'
- 'INC' => '', # e.g., '-I/usr/include/other'
- );
-
- The file Mytest.pm should start with something like this:
-
-
-
-
-
-
- PPPPaaaaggggeeee 2222
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- package Mytest;
-
- require Exporter;
- require DynaLoader;
-
- @ISA = qw(Exporter DynaLoader);
- # Items to export into callers namespace by default. Note: do not export
- # names by default without a very good reason. Use EXPORT_OK instead.
- # Do not simply export all your public functions/methods/constants.
- @EXPORT = qw(
-
- );
- $VERSION = '0.01';
-
- bootstrap Mytest $VERSION;
-
- # Preloaded methods go here.
-
- # Autoload methods go after __END__, and are processed by the autosplit program.
-
- 1;
- __END__
- # Below is the stub of documentation for your module. You better edit it!
-
- And the Mytest.xs file should look something like this:
-
- #ifdef __cplusplus
- extern "C" {
- #endif
- #include "EXTERN.h"
- #include "perl.h"
- #include "XSUB.h"
- #ifdef __cplusplus
- }
- #endif
-
- PROTOTYPES: DISABLE
-
- MODULE = Mytest PACKAGE = Mytest
-
- Let's edit the .xs file by adding this to the end of the file:
-
- void
- hello()
- CODE:
- printf("Hello, world!\n");
-
- Now we'll run "perl Makefile.PL". This will create a real Makefile,
- which make needs. Its output looks something like:
-
-
-
-
-
-
- PPPPaaaaggggeeee 3333
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- % perl Makefile.PL
- Checking if your kit is complete...
- Looks good
- Writing Makefile for Mytest
- %
-
- Now, running make will produce output that looks something like this
- (some long lines shortened for clarity):
-
- % make
- umask 0 && cp Mytest.pm ./blib/Mytest.pm
- perl xsubpp -typemap typemap Mytest.xs >Mytest.tc && mv Mytest.tc Mytest.c
- cc -c Mytest.c
- Running Mkbootstrap for Mytest ()
- chmod 644 Mytest.bs
- LD_RUN_PATH="" ld -o ./blib/PA-RISC1.1/auto/Mytest/Mytest.sl -b Mytest.o
- chmod 755 ./blib/PA-RISC1.1/auto/Mytest/Mytest.sl
- cp Mytest.bs ./blib/PA-RISC1.1/auto/Mytest/Mytest.bs
- chmod 644 ./blib/PA-RISC1.1/auto/Mytest/Mytest.bs
-
- Now, although there is already a test.pl template ready for us, for this
- example only, we'll create a special test script. Create a file called
- hello that looks like this:
-
- #! /opt/perl5/bin/perl
-
- use ExtUtils::testlib;
-
- use Mytest;
-
- Mytest::hello();
-
- Now we run the script and we should see the following output:
-
- % perl hello
- Hello, world!
- %
-
-
- EEEEXXXXAAAAMMMMPPPPLLLLEEEE 2222
-
- Now let's add to our extension a subroutine that will take a single
- argument and return 1 if the argument is even, 0 if the argument is odd.
-
- Add the following to the end of Mytest.xs:
-
-
-
-
-
-
-
-
-
-
- PPPPaaaaggggeeee 4444
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- int
- is_even(input)
- int input
- CODE:
- RETVAL = (input % 2 == 0);
- OUTPUT:
- RETVAL
-
- There does not need to be white space at the start of the "int input"
- line, but it is useful for improving readability. The semi-colon at the
- end of that line is also optional.
-
- Any white space may be between the "int" and "input". It is also okay
- for the four lines starting at the "CODE:" line to not be indented.
- However, for readability purposes, it is suggested that you indent them 8
- spaces (or one normal tab stop).
-
- Now rerun make to rebuild our new shared library.
-
- Now perform the same steps as before, generating a Makefile from the
- Makefile.PL file, and running make.
-
- To test that our extension works, we now need to look at the file
- test.pl. This file is set up to imitate the same kind of testing
- structure that Perl itself has. Within the test script, you perform a
- number of tests to confirm the behavior of the extension, printing "ok"
- when the test is correct, "not ok" when it is not. Change the print
- statement in the BEGIN block to print "1..4", and add the following code
- to the end of the file:
-
- print &Mytest::is_even(0) == 1 ? "ok 2" : "not ok 2", "\n";
- print &Mytest::is_even(1) == 0 ? "ok 3" : "not ok 3", "\n";
- print &Mytest::is_even(2) == 1 ? "ok 4" : "not ok 4", "\n";
-
- We will be calling the test script through the command "make test". You
- should see output that looks something like this:
-
- % make test
- PERL_DL_NONLAZY=1 /opt/perl5.002b2/bin/perl (lots of -I arguments) test.pl
- 1..4
- ok 1
- ok 2
- ok 3
- ok 4
- %
-
-
- WWWWHHHHAAAATTTT HHHHAAAASSSS GGGGOOOONNNNEEEE OOOONNNN????
-
- The program h2xs is the starting point for creating extensions. In later
- examples we'll see how we can use h2xs to read header files and generate
- templates to connect to C routines.
-
-
-
- PPPPaaaaggggeeee 5555
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- h2xs creates a number of files in the extension directory. The file
- Makefile.PL is a perl script which will generate a true Makefile to build
- the extension. We'll take a closer look at it later.
-
- The files <extension>.pm and <extension>.xs contain the meat of the
- extension. The .xs file holds the C routines that make up the extension.
- The .pm file contains routines that tell Perl how to load your extension.
-
- Generating and invoking the Makefile created a directory blib (which
- stands for "build library") in the current working directory. This
- directory will contain the shared library that we will build. Once we
- have tested it, we can install it into its final location.
-
- Invoking the test script via "make test" did something very important.
- It invoked perl with all those -I arguments so that it could find the
- various files that are part of the extension.
-
- It is _v_e_r_y important that while you are still testing extensions that you
- use "make test". If you try to run the test script all by itself, you
- will get a fatal error.
-
- Another reason it is important to use "make test" to run your test script
- is that if you are testing an upgrade to an already-existing version,
- using "make test" insures that you use your new extension, not the
- already-existing version.
-
- When Perl sees a use extension;, it searches for a file with the same
- name as the use'd extension that has a .pm suffix. If that file cannot
- be found, Perl dies with a fatal error. The default search path is
- contained in the @INC array.
-
- In our case, Mytest.pm tells perl that it will need the Exporter and
- Dynamic Loader extensions. It then sets the @ISA and @EXPORT arrays and
- the $VERSION scalar; finally it tells perl to bootstrap the module. Perl
- will call its dynamic loader routine (if there is one) and load the
- shared library.
-
- The two arrays that are set in the .pm file are very important. The @ISA
- array contains a list of other packages in which to search for methods
- (or subroutines) that do not exist in the current package. The @EXPORT
- array tells Perl which of the extension's routines should be placed into
- the calling package's namespace.
-
- It's important to select what to export carefully. Do NOT export method
- names and do NOT export anything else _b_y _d_e_f_a_u_l_t without a good reason.
-
- As a general rule, if the module is trying to be object-oriented then
- don't export anything. If it's just a collection of functions then you
- can export any of the functions via another array, called @EXPORT_OK.
-
-
-
-
-
-
- PPPPaaaaggggeeee 6666
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- See the _p_e_r_l_m_o_d manpage for more information.
-
- The $VERSION variable is used to ensure that the .pm file and the shared
- library are "in sync" with each other. Any time you make changes to the
- .pm or .xs files, you should increment the value of this variable.
-
- WWWWRRRRIIIITTTTIIIINNNNGGGG GGGGOOOOOOOODDDD TTTTEEEESSSSTTTT SSSSCCCCRRRRIIIIPPPPTTTTSSSS
-
- The importance of writing good test scripts cannot be overemphasized.
- You should closely follow the "ok/not ok" style that Perl itself uses, so
- that it is very easy and unambiguous to determine the outcome of each
- test case. When you find and fix a bug, make sure you add a test case
- for it.
-
- By running "make test", you ensure that your test.pl script runs and uses
- the correct version of your extension. If you have many test cases, you
- might want to copy Perl's test style. Create a directory named "t", and
- ensure all your test files end with the suffix ".t". The Makefile will
- properly run all these test files.
-
- EEEEXXXXAAAAMMMMPPPPLLLLEEEE 3333
-
- Our third extension will take one argument as its input, round off that
- value, and set the _a_r_g_u_m_e_n_t to the rounded value.
-
- Add the following to the end of Mytest.xs:
-
- void
- round(arg)
- double arg
- CODE:
- if (arg > 0.0) {
- arg = floor(arg + 0.5);
- } else if (arg < 0.0) {
- arg = ceil(arg - 0.5);
- } else {
- arg = 0.0;
- }
- OUTPUT:
- arg
-
- Edit the Makefile.PL file so that the corresponding line looks like this:
-
- 'LIBS' => ['-lm'], # e.g., '-lm'
-
- Generate the Makefile and run make. Change the BEGIN block to print out
- "1..9" and add the following to test.pl:
-
-
-
-
-
-
-
-
- PPPPaaaaggggeeee 7777
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- $i = -1.5; &Mytest::round($i); print $i == -2.0 ? "ok 5" : "not ok 5", "\n";
- $i = -1.1; &Mytest::round($i); print $i == -1.0 ? "ok 6" : "not ok 6", "\n";
- $i = 0.0; &Mytest::round($i); print $i == 0.0 ? "ok 7" : "not ok 7", "\n";
- $i = 0.5; &Mytest::round($i); print $i == 1.0 ? "ok 8" : "not ok 8", "\n";
- $i = 1.2; &Mytest::round($i); print $i == 1.0 ? "ok 9" : "not ok 9", "\n";
-
- Running "make test" should now print out that all nine tests are okay.
-
- You might be wondering if you can round a constant. To see what happens,
- add the following line to test.pl temporarily:
-
- &Mytest::round(3);
-
- Run "make test" and notice that Perl dies with a fatal error. Perl won't
- let you change the value of constants!
-
- WWWWHHHHAAAATTTT''''SSSS NNNNEEEEWWWW HHHHEEEERRRREEEE????
-
- Two things are new here. First, we've made some changes to Makefile.PL.
- In this case, we've specified an extra library to link in, the math
- library libm. We'll talk later about how to write XSUBs that can call
- every routine in a library.
-
- Second, the value of the function is being passed back not as the
- function's return value, but through the same variable that was passed
- into the function.
-
- IIIINNNNPPPPUUUUTTTT AAAANNNNDDDD OOOOUUUUTTTTPPPPUUUUTTTT PPPPAAAARRRRAAAAMMMMEEEETTTTEEEERRRRSSSS
-
- You specify the parameters that will be passed into the XSUB just after
- you declare the function return value and name. Each parameter line
- starts with optional white space, and may have an optional terminating
- semicolon.
-
- The list of output parameters occurs after the OUTPUT: directive. The
- use of RETVAL tells Perl that you wish to send this value back as the
- return value of the XSUB function. In Example 3, the value we wanted
- returned was contained in the same variable we passed in, so we listed it
- (and not RETVAL) in the OUTPUT: section.
-
- TTTTHHHHEEEE XXXXSSSSUUUUBBBBPPPPPPPP CCCCOOOOMMMMPPPPIIIILLLLEEEERRRR
-
- The compiler xsubpp takes the XS code in the .xs file and converts it
- into C code, placing it in a file whose suffix is .c. The C code created
- makes heavy use of the C functions within Perl.
-
- TTTTHHHHEEEE TTTTYYYYPPPPEEEEMMMMAAAAPPPP FFFFIIIILLLLEEEE
-
- The xsubpp compiler uses rules to convert from Perl's data types (scalar,
- array, etc.) to C's data types (int, char *, etc.). These rules are
- stored in the typemap file ($PERLLIB/ExtUtils/typemap). This file is
- split into three parts.
-
-
-
- PPPPaaaaggggeeee 8888
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- The first part attempts to map various C data types to a coded flag,
- which has some correspondence with the various Perl types. The second
- part contains C code which xsubpp uses for input parameters. The third
- part contains C code which xsubpp uses for output parameters. We'll talk
- more about the C code later.
-
- Let's now take a look at a portion of the .c file created for our
- extension.
-
- XS(XS_Mytest_round)
- {
- dXSARGS;
- if (items != 1)
- croak("Usage: Mytest::round(arg)");
- {
- double arg = (double)SvNV(ST(0)); /* XXXXX */
- if (arg > 0.0) {
- arg = floor(arg + 0.5);
- } else if (arg < 0.0) {
- arg = ceil(arg - 0.5);
- } else {
- arg = 0.0;
- }
- sv_setnv(ST(0), (double)arg); /* XXXXX */
- }
- XSRETURN(1);
- }
-
- Notice the two lines marked with "XXXXX". If you check the first section
- of the typemap file, you'll see that doubles are of type T_DOUBLE. In
- the INPUT section, an argument that is T_DOUBLE is assigned to the
- variable arg by calling the routine SvNV on something, then casting it to
- double, then assigned to the variable arg. Similarly, in the OUTPUT
- section, once arg has its final value, it is passed to the sv_setnv
- function to be passed back to the calling subroutine. These two
- functions are explained in the _p_e_r_l_g_u_t_s manpage; we'll talk more later
- about what that "_S_T(0)" means in the section on the argument stack.
-
- WWWWAAAARRRRNNNNIIIINNNNGGGG
-
- In general, it's not a good idea to write extensions that modify their
- input parameters, as in Example 3. However, to accommodate better
- calling pre-existing C routines, which often do modify their input
- parameters, this behavior is tolerated. The next example will show how
- to do this.
-
- EEEEXXXXAAAAMMMMPPPPLLLLEEEE 4444
-
- In this example, we'll now begin to write XSUBs that will interact with
- predefined C libraries. To begin with, we will build a small library of
- our own, then let h2xs write our .pm and .xs files for us.
-
-
-
-
- PPPPaaaaggggeeee 9999
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- Create a new directory called Mytest2 at the same level as the directory
- Mytest. In the Mytest2 directory, create another directory called mylib,
- and cd into that directory.
-
- Here we'll create some files that will generate a test library. These
- will include a C source file and a header file. We'll also create a
- Makefile.PL in this directory. Then we'll make sure that running make at
- the Mytest2 level will automatically run this Makefile.PL file and the
- resulting Makefile.
-
- In the testlib directory, create a file mylib.h that looks like this:
-
- #define TESTVAL 4
-
- extern double foo(int, long, const char*);
-
- Also create a file mylib.c that looks like this:
-
- #include <stdlib.h>
- #include "./mylib.h"
-
- double
- foo(a, b, c)
- int a;
- long b;
- const char * c;
- {
- return (a + b + atof(c) + TESTVAL);
- }
-
- And finally create a file Makefile.PL that looks like this:
-
- use ExtUtils::MakeMaker;
- $Verbose = 1;
- WriteMakefile(
- NAME => 'Mytest2::mylib',
- SKIP => [qw(all static static_lib dynamic dynamic_lib)],
- clean => {'FILES' => 'libmylib$(LIB_EXT)'},
- );
-
- sub MY::top_targets {
- '
- all :: static
-
- static :: libmylib$(LIB_EXT)
-
- libmylib$(LIB_EXT): $(O_FILES)
- $(AR) cr libmylib$(LIB_EXT) $(O_FILES)
- $(RANLIB) libmylib$(LIB_EXT)
-
- ';
- }
-
-
-
- PPPPaaaaggggeeee 11110000
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- We will now create the main top-level Mytest2 files. Change to the
- directory above Mytest2 and run the following command:
-
- % h2xs -O -n Mytest2 ./Mytest2/mylib/mylib.h
-
- This will print out a warning about overwriting Mytest2, but that's okay.
- Our files are stored in Mytest2/mylib, and will be untouched.
-
- The normal Makefile.PL that h2xs generates doesn't know about the mylib
- directory. We need to tell it that there is a subdirectory and that we
- will be generating a library in it. Let's add the following key-value
- pair to the WriteMakefile call:
-
- 'MYEXTLIB' => 'mylib/libmylib$(LIB_EXT)',
-
- and a new replacement subroutine too:
-
- sub MY::postamble {
- '
- $(MYEXTLIB): mylib/Makefile
- cd mylib && $(MAKE) $(PASTHRU)
- ';
- }
-
- (Note: Most makes will require that there be a tab character that indents
- the line cd mylib && $(MAKE) $(PASTHRU), similarly for the Makefile in
- the subdirectory.)
-
- Let's also fix the MANIFEST file so that it accurately reflects the
- contents of our extension. The single line that says "mylib" should be
- replaced by the following three lines:
-
- mylib/Makefile.PL
- mylib/mylib.c
- mylib/mylib.h
-
- To keep our namespace nice and unpolluted, edit the .pm file and change
- the lines setting @EXPORT to @EXPORT_OK (there are two: one in the line
- beginning "use vars" and one setting the array itself). Finally, in the
- .xs file, edit the #include line to read:
-
- #include "mylib/mylib.h"
-
- And also add the following function definition to the end of the .xs
- file:
-
-
-
-
-
-
-
-
-
-
- PPPPaaaaggggeeee 11111111
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- double
- foo(a,b,c)
- int a
- long b
- const char * c
- OUTPUT:
- RETVAL
-
- Now we also need to create a typemap file because the default Perl
- doesn't currently support the const char * type. Create a file called
- typemap and place the following in it:
-
- const char * T_PV
-
- Now run perl on the top-level Makefile.PL. Notice that it also created a
- Makefile in the mylib directory. Run make and see that it does cd into
- the mylib directory and run make in there as well.
-
- Now edit the test.pl script and change the BEGIN block to print "1..4",
- and add the following lines to the end of the script:
-
- print &Mytest2::foo(1, 2, "Hello, world!") == 7 ? "ok 2\n" : "not ok 2\n";
- print &Mytest2::foo(1, 2, "0.0") == 7 ? "ok 3\n" : "not ok 3\n";
- print abs(&Mytest2::foo(0, 0, "-3.4") - 0.6) <= 0.01 ? "ok 4\n" : "not ok 4\n";
-
- (When dealing with floating-point comparisons, it is often useful not to
- check for equality, but rather the difference being below a certain
- epsilon factor, 0.01 in this case)
-
- Run "make test" and all should be well.
-
- WWWWHHHHAAAATTTT HHHHAAAASSSS HHHHAAAAPPPPPPPPEEEENNNNEEEEDDDD HHHHEEEERRRREEEE????
-
- Unlike previous examples, we've now run h2xs on a real include file.
- This has caused some extra goodies to appear in both the .pm and .xs
- files.
-
- +o In the .xs file, there's now a #include declaration with the full
- path to the mylib.h header file.
-
- +o There's now some new C code that's been added to the .xs file. The
- purpose of the constant routine is to make the values that are
- #define'd in the header file available to the Perl script (in this
- case, by calling &main::TESTVAL). There's also some XS code to allow
- calls to the constant routine.
-
- +o The .pm file has exported the name TESTVAL in the @EXPORT array.
- This could lead to name clashes. A good rule of thumb is that if the
- #define is going to be used by only the C routines themselves, and
- not by the user, they should be removed from the @EXPORT array.
- Alternately, if you don't mind using the "fully qualified name" of a
- variable, you could remove most or all of the items in the @EXPORT
-
-
-
- PPPPaaaaggggeeee 11112222
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- array.
-
- +o If our include file contained #include directives, these would not be
- processed at all by h2xs. There is no good solution to this right
- now.
-
- We've also told Perl about the library that we built in the mylib
- subdirectory. That required the addition of only the MYEXTLIB variable
- to the WriteMakefile call and the replacement of the postamble subroutine
- to cd into the subdirectory and run make. The Makefile.PL for the
- library is a bit more complicated, but not excessively so. Again we
- replaced the postamble subroutine to insert our own code. This code
- specified simply that the library to be created here was a static archive
- (as opposed to a dynamically loadable library) and provided the commands
- to build it.
-
- SSSSPPPPEEEECCCCIIIIFFFFYYYYIIIINNNNGGGG AAAARRRRGGGGUUUUMMMMEEEENNNNTTTTSSSS TTTTOOOO XXXXSSSSUUUUBBBBPPPPPPPP
-
- With the completion of Example 4, we now have an easy way to simulate
- some real-life libraries whose interfaces may not be the cleanest in the
- world. We shall now continue with a discussion of the arguments passed
- to the xsubpp compiler.
-
- When you specify arguments in the .xs file, you are really passing three
- pieces of information for each one listed. The first piece is the order
- of that argument relative to the others (first, second, etc). The second
- is the type of argument, and consists of the type declaration of the
- argument (e.g., int, char*, etc). The third piece is the exact way in
- which the argument should be used in the call to the library function
- from this XSUB. This would mean whether or not to place a "&" before the
- argument or not, meaning the argument expects to be passed the address of
- the specified data type.
-
- There is a difference between the two arguments in this hypothetical
- function:
-
- int
- foo(a,b)
- char &a
- char * b
-
- The first argument to this function would be treated as a char and
- assigned to the variable a, and its address would be passed into the
- function foo. The second argument would be treated as a string pointer
- and assigned to the variable b. The _v_a_l_u_e of b would be passed into the
- function foo. The actual call to the function foo that xsubpp generates
- would look like this:
-
- foo(&a, b);
-
- Xsubpp will identically parse the following function argument lists:
-
-
-
-
- PPPPaaaaggggeeee 11113333
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- char &a
- char&a
- char & a
-
- However, to help ease understanding, it is suggested that you place a "&"
- next to the variable name and away from the variable type), and place a
- "*" near the variable type, but away from the variable name (as in the
- complete example above). By doing so, it is easy to understand exactly
- what will be passed to the C function -- it will be whatever is in the
- "last column".
-
- You should take great pains to try to pass the function the type of
- variable it wants, when possible. It will save you a lot of trouble in
- the long run.
-
- TTTTHHHHEEEE AAAARRRRGGGGUUUUMMMMEEEENNNNTTTT SSSSTTTTAAAACCCCKKKK
-
- If we look at any of the C code generated by any of the examples except
- example 1, you will notice a number of references to _S_T(n), where n is
- usually 0. The "ST" is actually a macro that points to the n'th argument
- on the argument stack. _S_T(0) is thus the first argument passed to the
- XSUB, _S_T(1) is the second argument, and so on.
-
- When you list the arguments to the XSUB in the .xs file, that tells
- xsubpp which argument corresponds to which of the argument stack (i.e.,
- the first one listed is the first argument, and so on). You invite
- disaster if you do not list them in the same order as the function
- expects them.
-
- EEEEXXXXTTTTEEEENNNNDDDDIIIINNNNGGGG YYYYOOOOUUUURRRR EEEEXXXXTTTTEEEENNNNSSSSIIIIOOOONNNN
-
- Sometimes you might want to provide some extra methods or subroutines to
- assist in making the interface between Perl and your extension simpler or
- easier to understand. These routines should live in the .pm file.
- Whether they are automatically loaded when the extension itself is loaded
- or loaded only when called depends on where in the .pm file the
- subroutine definition is placed.
-
- DDDDOOOOCCCCUUUUMMMMEEEENNNNTTTTIIIINNNNGGGG YYYYOOOOUUUURRRR EEEEXXXXTTTTEEEENNNNSSSSIIIIOOOONNNN
-
- There is absolutely no excuse for not documenting your extension.
- Documentation belongs in the .pm file. This file will be fed to pod2man,
- and the embedded documentation will be converted to the manpage format,
- then placed in the blib directory. It will be copied to Perl's man page
- directory when the extension is installed.
-
- You may intersperse documentation and Perl code within the .pm file. In
- fact, if you want to use method autoloading, you must do this, as the
- comment inside the .pm file explains.
-
-
-
-
-
-
- PPPPaaaaggggeeee 11114444
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- See the _p_e_r_l_p_o_d manpage for more information about the pod format.
-
- IIIINNNNSSSSTTTTAAAALLLLLLLLIIIINNNNGGGG YYYYOOOOUUUURRRR EEEEXXXXTTTTEEEENNNNSSSSIIIIOOOONNNN
-
- Once your extension is complete and passes all its tests, installing it
- is quite simple: you simply run "make install". You will either need to
- have write permission into the directories where Perl is installed, or
- ask your system administrator to run the make for you.
-
- SSSSEEEEEEEE AAAALLLLSSSSOOOO
-
- For more information, consult the _p_e_r_l_g_u_t_s manpage, the _p_e_r_l_x_s manpage,
- the _p_e_r_l_m_o_d manpage, and the _p_e_r_l_p_o_d manpage.
-
- AAAAuuuutttthhhhoooorrrr
-
- Jeff Okamoto <_o_k_a_m_o_t_o@_c_o_r_p._h_p._c_o_m>
-
- Reviewed and assisted by Dean Roehrich, Ilya Zakharevich, Andreas Koenig,
- and Tim Bunce.
-
- LLLLaaaasssstttt CCCChhhhaaaannnnggggeeeedddd
-
- 1996/7/10
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- PPPPaaaaggggeeee 11115555
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- PPPPaaaaggggeeee 11116666
-
-
-
-
-
-
-